package com.jwsoft.manager.core.integration.addressParse;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ReUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bifang.engine.cache.redis.RedisHelper;
import com.bifang.module.base.common.vo.dict.DictAreaVO;
import com.bifang.module.base.common.vo.dict.SelectVO;
import com.bifang.module.base.common.vo.org.OrgTreeVO;
import com.bifang.module.base.common.vo.tree.TreeVO;
import com.bifang.module.base.core.integration.DictIntegration;
import com.bifang.module.system.core.integration.OrgIntegration;
import com.jwsoft.manager.common.constant.EduCache;
import com.jwsoft.manager.common.enums.AreaEnum;
import com.jwsoft.manager.common.vo.addressParse.Address;
import com.jwsoft.manager.common.vo.addressParse.AddressInfo;
import com.jwsoft.manager.common.vo.eduAddressTreeInitial.EduAddressTreeInitialVO;
import com.jwsoft.manager.core.dao.model.EduAddressTreeOriginal;
import com.jwsoft.manager.core.dao.service.EduAddressTreeOriginalService;
import com.jwsoft.manager.core.dao.service.EduAddressTreeService;
import com.jwsoft.manager.core.util.EduHelper;
import com.jwsoft.manager.core.util.IKAnalyzerUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 解析地区
 */
@Slf4j
@Service
public class AreaParse {
    @Autowired
    private  AddressDataLoader addressDataLoader;
    @Autowired
    private EduAddressTreeOriginalService originalService;
    @Autowired
    private EduHelper eduHelper;
    @Autowired
    private EduAddressTreeOriginalService eduAddressTreeOriginalService;
    @Autowired
    private RedisHelper redisHelper;
    @Value("${system.config.snowflake.workerId:1}")
    private Long workerId;
    @Autowired
    private DictIntegration dictIntegration;
    private List<Address> addressAll=new ArrayList<>();
    /**
     * 地名标识常量
     */
    public static final String PLACE_NAME_CHAR = "省市区县州街道镇乡特别行政自治村社区";
    /**
     * 乡镇街道正则
     */
    private static final Pattern PATTERN_TWON = Pattern.compile("[\\s\\S]+(乡|镇|乡镇|街道)");
    /**
     * 村、社区正则
     */
    private static final Pattern PATTERN_VILLAGE = Pattern.compile("[\\s\\S]+(村|社区)");

    /**
     * 街道正则  - 非行政区划
     */
    private static final Pattern PATTERN_STREET_NUMBER = Pattern.compile("[\\s\\S]+(街道|街|道|巷|路|桥)+(东|南|西|北|以西|以东|以南|以北)?([\\d-]+号)?");
    private static final Pattern PATTERN_STREET = Pattern.compile("[\\s\\S]+(街道|街|道|巷|路|桥)");

    /**
     * 小区正则 - 非行政区划
     */
    private static final Pattern PATTERN_RESIDENTIAL = Pattern.compile("([\\s\\S]+)(小区|公园|花园|地块|社区|村|墅|弄|寓|顾|家|月|庄园|岛|座|院|府|邸|期|地|庭|阁|居|轩|苑|庄|巷|园|坊|湾|城|馆|区|门|郡)+(东|南|西|北|以西|以东|以南|以北)?(?:[\\)）])?");
    /**
     * 路正则  -非行政区划
     */
    private static final Pattern PATTERN_ROAD = Pattern.compile("[\\s\\S]+(路|街道|街|沿|道路|道|巷)+(南段|北段|东段|西段|以西|以东|以南|以北)?+([\\d-]+(号|弄))?");

    private static final Pattern PATTERN_ROAD_PREFIX= Pattern.compile("(东|南|西|北|以东|以南|以西|以北)?\\d*[-]*\\d*+(号|弄|排)");

    private static final Pattern PATTERN_ROAD_NUMBER = Pattern.compile("\\d+-?\\d*+(号|弄|排)");
    /**
     * 楼房号正则  -非行政区划
     */
    private static final Pattern PATTERN_HOUSE = Pattern.compile("([a-zA-Z\\d一二三四五六七八九十百千万\\d+-?]+(?:\\([^)]*\\))?+(号楼|楼|幢|号|弄|栋)+)(?:\\([^)]*\\))?");
    /**
     * 单元号正则 - 非行政区划
     */
    private static final Pattern PATTERN_UNIT =Pattern.compile("[a-zA-Z\\d零一二三四五六七八九十百千万]+(单元|座)");

    /**
     * 房间号正则  --非行政区划
     */
    private static final Pattern PATTERN_ROOM_NUMBER =Pattern.compile("([a-zA-Z\\d-]+(地下室|阁室|阁|室|地))");

    /**
     * 前缀字符特殊处理，匹配时候会自动处理掉符合正则的文字
     */
    private Pattern keyCharPattern = Pattern.compile("^[" + PLACE_NAME_CHAR + "]+");

    private final Map<Serializable, Address> areaMap = new HashMap<>();
    private boolean initAreaMap = false;



    public Address parse(AddressInfo addressInfo, TextHolder textHolder, List<EduAddressTreeInitialVO> parseNodeList) {

        textHolder.setText(Convert.toDBC(textHolder.getText()));
        textHolder.removeText(" ");
        addressInfo.setOriginAdd(textHolder.getText());
        textHolder.setText(textHolder.getText().replaceAll("[,*&*@!~.，、,.，。\\s！#]", ""));
        return parseArea(addressInfo, textHolder,parseNodeList);
    }


    public Address parseArea(AddressInfo addressInfo, TextHolder textHolder, List<EduAddressTreeInitialVO> parseNodeList) {

        //获取基本信息
        List<String> areaCodeList = new ArrayList<>();
        DictAreaVO dictAreaVO = new DictAreaVO();
        dictAreaVO.setParentId(eduHelper.thisAreaCode());
        dictAreaVO.setPermissionFlag(false);
        List<SelectVO> districtByOrg = dictIntegration.getDistrictByOrg(dictAreaVO);
        if(!CollectionUtils.isEmpty(districtByOrg)){
            areaCodeList = districtByOrg.stream()
                    .map(SelectVO::getDictKey)
                    .collect(Collectors.toList());
        }else{
            areaCodeList.add(eduHelper.thisAreaCode());
        }
        //获取当前统筹区化行政编码
        QueryWrapper<EduAddressTreeOriginal> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .in(EduAddressTreeOriginal::getAreaCode,areaCodeList)
                .eq(EduAddressTreeOriginal::getAreaType,"district");
        //获取当前统筹区化所属参数表id
        List<EduAddressTreeOriginal> areaNodeOriginals = eduAddressTreeOriginalService.list(queryWrapper);

        String text = textHolder.getText();
        List<Address> addresses = addressDataLoader.loadData();
        Address retAddress = null;
        addressAll=addresses;
        Long parentId=0L;
        // 匹配省
        List<AlternativeData> provinceList = match(text, 0, addresses, null,addressInfo);
        text=replace(provinceList,textHolder);
        if(!CollectionUtils.isEmpty(provinceList)){
            retAddress=provinceList.get(0).getData();
        }
        // 匹配市
        List<AlternativeData> cityList = bestMatch(text, 1, provinceList,addressInfo,areaCodeList,areaNodeOriginals);
        text=replace(cityList,textHolder);
        if(!CollectionUtils.isEmpty(cityList)){
            List<Long> parentIds = areaNodeOriginals.stream()
                    .map(EduAddressTreeOriginal::getParentId).collect(Collectors.toList());
            retAddress=cityList.get(0).getData();
            List<EduAddressTreeOriginal> list = eduAddressTreeOriginalService.list(Wrappers.<EduAddressTreeOriginal>lambdaQuery()
                    .in(EduAddressTreeOriginal::getAddressId, parentIds));
            if (list.size() == 1){
                EduAddressTreeOriginal cityOriginal = list.get(0);
                if (!cityOriginal.getAddressId().equals(retAddress.getAddressId())){
                    addressInfo.setIsOtherCity(true);
                    addressInfo.setDetail(text);
                    return retAddress;
                }
            }
        }
        boolean flag=false;
        if (CollUtil.isEmpty(provinceList)&&CollUtil.isEmpty(cityList)){
            String areaCode=eduHelper.thisAreaCode();
            if (StringUtils.isNotBlank(areaCode)){
                Address address=AddressDataUtil.getAssignLevel(addressAll,0,areaCode);
                if (address!=null){
                    setAddressInfo(address,addressInfo);
                    flag=true;
                }
            }
        }
        // 匹配区、县
        List<AlternativeData> areaList = bestMatch(text, 2, cityList,addressInfo,areaCodeList,areaNodeOriginals);
        text=replace(areaList,textHolder);
        if(!CollectionUtils.isEmpty(areaList)){
            //如果说匹配到了，判断是否为统筹区化下的地址
            List<Long> areaNodeId = areaNodeOriginals.stream().map(EduAddressTreeOriginal::getAddressId).collect(Collectors.toList());
            retAddress=areaList.get(0).getData();
            if (!areaNodeId.contains(areaList.get(0).getAddressId())){
                addressInfo.setDetail(text);
                //表示是区外地址，直接返回
                return retAddress;
            }
        } else if (areaList.size() == 1) {
            //校验指针映射是否存在
            checkMajorPoint(addressInfo,areaList.get(0).getData().getAddressId(),parseNodeList);
        }
        // 匹配乡镇街道
        List<AlternativeData> streetList = bestMatch(text, 3, areaList,addressInfo,areaCodeList,areaNodeOriginals);
        if(!CollectionUtils.isEmpty(streetList)){
            //判断是否匹配到多个了
            if (streetList.size() >1){
                String textTemp = text;
                textTemp=replace(streetList,textHolder);
                //如果匹配到了多个，进行截取尝试重新匹配
                List<AlternativeData> alternativeData = bestMatch(textTemp, 3, areaList, addressInfo, areaCodeList, areaNodeOriginals);
                if (!CollectionUtils.isEmpty(alternativeData) && alternativeData.size() == 1){
                    //如果截取重新匹配后，匹配到一个，进行返回
                    text=replace(alternativeData,textHolder);
                    streetList.clear();
                    streetList = alternativeData;
                    retAddress=alternativeData.get(0).getData();
                }else {
                    //如果还是有多个，返回空对象
                    streetList = new ArrayList<>();
                    retAddress=new Address();
                }
            }else if (streetList.size()==1){
                retAddress=streetList.get(0).getData();
            }else{
                retAddress=new Address();
            }
        }
        if (streetList.size() == 1){
            //校验指针映射是否存在
            checkMajorPoint(addressInfo,streetList.get(0).getData().getAddressId(),parseNodeList);
        }
        if (flag&&CollUtil.isEmpty(areaList)&&CollUtil.isEmpty(streetList)){
            addressInfo.setProvinceCode(null);
            addressInfo.setProvinceId(null);
            addressInfo.setProvince(null);
            addressInfo.setCityCode(null);
            addressInfo.setCity(null);
            addressInfo.setCityId(null);
            addressInfo.setDistrictId(null);
            addressInfo.setDistrict(null);
            addressInfo.setDistrictCode(null);
            /***
             //匹配村社区
             List<AlternativeData> villageList = bestMatch(text, 4, streetList,addressInfo);
             text=replace(villageList,textHolder);
             //匹配小区
             List<AlternativeData> detailList = bestMatch(text, 5, villageList,addressInfo);
             text=replace(detailList,textHolder);
             //如果浙江省区县和街道社区，小区 都未匹配到直接返回匹配失败
             ***/
            addressInfo.setDetail(text);
            return new Address();
        }
        text=replace(streetList,textHolder);
        /***
         if (cityList.isEmpty()&&areaList.isEmpty()&&streetList.isEmpty()){
         //如果区县和街道都为匹配到直接返回匹配失败
         // 获取详细地址
         addressInfo.setDetail(text);
         return false;
         }

         //匹配村社区
         List<AlternativeData> villageList = bestMatch(text, 4, streetList,addressInfo);
         text=replace(villageList,textHolder);
         //匹配小区
         List<AlternativeData> detailList = bestMatch(text, 5, villageList,addressInfo);
         text=replace(detailList,textHolder);
         if (!villageList.isEmpty()) {
         if (villageList.get(0).getAreaType().equalsIgnoreCase(AreaEnum.village.getType())){
         // 匹配路、街
         List<AlternativeData> roadList = bestMatch(text, 5, villageList,addressInfo);
         text=replace(roadList,textHolder);
         }
         }
         if (StringUtils.isNotBlank(text)) {
         String textStr = "";
         try {
         textStr = IKAnalyzerUtil.wordSegmentationToString(text);
         } catch (IOException e) {
         log.error("分词失败" + e.getMessage());
         }
         if (StringUtils.isNotBlank(textStr)) {
         List<String> textList = Arrays.stream(textStr.split("|")).map(s -> s).collect(Collectors.toList());
         String matcherText="";
         int matcherCount=0;
         boolean matchFlag=true;
         //村社区
         for (String str : textList) {
         Matcher matcher = PATTERN_VILLAGE.matcher(matcherText);
         if (matcher.find()) {
         matcherCount=matcherCount+1;
         matcherText=matcherText+str;
         }else{

         }

         }


         }
         }
         ***/
        // 获取详细地址
        addressInfo.setDetail(text);
        return retAddress;
    }

    /**
     * 校验指针映射是否存在
     * @param addressInfo
     * @param addressId
     * @param parseNodeList
     */
    public void checkMajorPoint(AddressInfo addressInfo,Long addressId,List<EduAddressTreeInitialVO> parseNodeList) {
        EduAddressTreeOriginal original = originalService.getById(addressId);
        if (original != null && original.getMajorPointer() != 0L) {
            //根据指针映射id获取上级链路数据，没有表示映射的节点不存在
            List<EduAddressTreeOriginal> originalLinkList
                    = originalService.getAllLinkByOriginalId(original.getMajorPointer());
            if (CollectionUtil.isEmpty(originalLinkList)){
                return;
            }
            List<EduAddressTreeInitialVO> list = Convert.toList(EduAddressTreeInitialVO.class, originalLinkList);
            parseNodeList.clear();
            parseNodeList.addAll(list);
            for (EduAddressTreeInitialVO initialVO : parseNodeList) {
                //修正节点后 设置省市县数据到addressInfo
                if (initialVO.getAreaType().equals(AreaEnum.province.getType())){
                    addressInfo.setProvince(initialVO.getAreaName());
                    addressInfo.setProvinceId(initialVO.getAddressId());
                    addressInfo.setProvinceCode(initialVO.getAreaCode());
                }
                if (initialVO.getAreaType().equals(AreaEnum.city.getType())){
                    addressInfo.setCity(initialVO.getAreaName());
                    addressInfo.setCityId(initialVO.getAddressId());
                    addressInfo.setCityCode(initialVO.getAreaCode());
                }
                if (initialVO.getAreaType().equals(AreaEnum.district.getType())){
                    addressInfo.setDistrict(initialVO.getAreaName());
                    addressInfo.setDistrictId(initialVO.getAddressId());
                    addressInfo.setDistrictCode(initialVO.getAreaCode());
                }
                if (initialVO.getAreaType().equals(AreaEnum.town.getType())){
                    addressInfo.setTown(initialVO.getAreaName());
                    addressInfo.setTownId(initialVO.getAddressId());
                    addressInfo.setTownCode(initialVO.getAreaCode());
                }
            }
        }
    }


    /**
     * 分解详细地址
     * @param addressInfo
     * @param parseNodeList
     * @return
     */
    public AddressInfo parseAddressDetail(AddressInfo addressInfo, List<EduAddressTreeInitialVO> parseNodeList) {
        //1.设置省市区街道信息
        if (CollectionUtils.isEmpty(parseNodeList)){
            setBaseInfo(addressInfo,parseNodeList);
        }
        addressInfo.setErrorStatus(0);
        addressInfo.setOtherAddress("");
        if (StringUtils.isEmpty(addressInfo.getDistrict())) {
            addressInfo.setErrorStatus(1);
            addressInfo.setErrorDetail("无法从输入地址中定位到具体区县！");
        }
        if (addressInfo.getIsOtherCity()){
            addressInfo.setErrorStatus(9);
            addressInfo.setErrorDetail("识别区外地址，不予处理！");
            return addressInfo;
        }
        return addressInfo;
    }

    String parseRoadNumber(String address, AddressInfo addressInfo, List<EduAddressTreeInitialVO> parseNodeList) {
        if (!StringUtils.isEmpty(addressInfo.getName())){
            return address;
        }
        if(StringUtils.isEmpty(addressInfo.getRoadNumber())){
            Matcher matcher = PATTERN_ROAD_PREFIX.matcher(address);
            String matcherText = "";
            if (matcher.find()){
                // 获取匹配的部分
                matcherText = matcher.group();
                if (address.startsWith(matcherText)){
                    addressInfo.setRoadNumber(matcherText);
                    address = address.replace(matcherText,"");
                    Snowflake snowflake = IdUtil.getSnowflake(workerId, (int) (Math.random() * 20 + 1));
                    EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
                    addressTreeInitial.setAreaName(addressInfo.getRoadNumber());
                    addressTreeInitial.setAddressId(snowflake.nextId());
                    addressTreeInitial.setAreaType(AreaEnum.roadNumber.getType());
                    if (parseNodeList.size()-1 >= 0){
                        addressTreeInitial.setParentId(parseNodeList.get(parseNodeList.size() - 1).getAddressId());
                    }
                    parseNodeList.add(addressTreeInitial);
                }
            }
        }
        return address;
    }

    void parseOther(String address, AddressInfo addressInfo, List<EduAddressTreeInitialVO> parseNodeList) {
        if (!StringUtils.isEmpty(address)){
            addressInfo.setOtherAddress(addressInfo.getOtherAddress()+address);
        }
        if (!org.springframework.util.StringUtils.isEmpty(addressInfo.getOtherAddress())){
            Snowflake snowflake = IdUtil.getSnowflake(workerId, (int) (Math.random() * 20 + 1));
            EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
            addressTreeInitial.setAreaName(addressInfo.getOtherAddress());
            addressTreeInitial.setAddressId(snowflake.nextId());
            addressTreeInitial.setAreaType(AreaEnum.other.getType());
            if (parseNodeList.size() - 1 >= 0){
                addressTreeInitial.setParentId(parseNodeList.get(parseNodeList.size() - 1).getAddressId());
            }
            parseNodeList.add(addressTreeInitial);
        }
    }

    /**
     * 设置省，市，县，街道等信息
     * @param addressInfo
     * @param parseNodeList
     */
    private void setBaseInfo(AddressInfo addressInfo, List<EduAddressTreeInitialVO> parseNodeList) {
        Snowflake snowflake = IdUtil.getSnowflake(workerId, (int) (Math.random() * 20 + 1));
        //设置 province
        if (StringUtils.isNotBlank(addressInfo.getProvince())){
            EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
            addressTreeInitial.setAreaName(addressInfo.getProvince());
            addressTreeInitial.setAreaCode(addressInfo.getProvinceCode());
            if (addressInfo.getProvinceId()!=null){
                addressTreeInitial.setAddressId(addressInfo.getProvinceId());
            }else{
                addressTreeInitial.setAddressId(snowflake.nextId());
            }
            addressTreeInitial.setAreaType(AreaEnum.province.getType());
            parseNodeList.add(addressTreeInitial);
        }

        //设置 city
        if (StringUtils.isNotBlank(addressInfo.getCity())){
            EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
            addressTreeInitial.setAreaName(addressInfo.getCity());
            addressTreeInitial.setAreaCode(addressInfo.getCityCode());
            if (addressInfo.getCityId()!=null){
                addressTreeInitial.setAddressId(addressInfo.getCityId());
            }else{
                addressTreeInitial.setAddressId(snowflake.nextId());
            }
            addressTreeInitial.setAreaType(AreaEnum.city.getType());
            if (parseNodeList.size() - 1>= 0){
                addressTreeInitial.setParentId(parseNodeList.get(parseNodeList.size() - 1).getAddressId());
            }
            parseNodeList.add(addressTreeInitial);
        }

        //设置 district
        if (StringUtils.isNotBlank(addressInfo.getDistrict())){
            EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
            addressTreeInitial.setAreaName(addressInfo.getDistrict());
            addressTreeInitial.setAreaCode(addressInfo.getDistrictCode());
            if (addressInfo.getDistrictId()!=null){
                addressTreeInitial.setAddressId(addressInfo.getDistrictId());
            }else{
                addressTreeInitial.setAddressId(snowflake.nextId());
            }
            addressTreeInitial.setAddressId(addressInfo.getDistrictId());
            addressTreeInitial.setAreaType(AreaEnum.district.getType());
            if (parseNodeList.size() - 1 >= 0){
                addressTreeInitial.setParentId(parseNodeList.get(parseNodeList.size() - 1).getAddressId());
            }
            parseNodeList.add(addressTreeInitial);
        }
        //设置 town
        if (StringUtils.isNotBlank(addressInfo.getTown())){
            EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
            addressTreeInitial.setAreaName(addressInfo.getTown());
            addressTreeInitial.setAreaCode(addressInfo.getTownCode());
            if (addressInfo.getTownId()!=null){
                addressTreeInitial.setAddressId(addressInfo.getTownId());
            }else{
                addressTreeInitial.setAddressId(snowflake.nextId());
            }
            addressTreeInitial.setAreaType(AreaEnum.town.getType());
            if (parseNodeList.size() - 1 >= 0){
                addressTreeInitial.setParentId(parseNodeList.get(parseNodeList.size() - 1).getAddressId());
            }
            parseNodeList.add(addressTreeInitial);
        }
    }

    /**
     * 识别小区，其他地址描述
     *
     * @param address
     * @param addressInfo
     * @param parseNodeList
     * @return
     */
    String parseResidential(String address, AddressInfo addressInfo, List<EduAddressTreeInitialVO> parseNodeList) {
        if(StringUtils.isEmpty(addressInfo.getName())){
            Matcher matcher = PATTERN_RESIDENTIAL.matcher(address);
            String matcherText = "";
            if (matcher.find()) {
                // 获取匹配的部分
                matcherText = matcher.group();
                //设置小区花园信息
                addressInfo.setName(matcherText);
                //判断address 是否以matcherText开头
                if (!address.startsWith(matcherText)){
                    address = setPrefixNode(address,matcherText,parseNodeList);
                }else{
                    //如果是以matcherText开头，就直接去除
                    address = address.replace(matcherText, "");
                }
            }
        }

        //设置detail
        if (!org.springframework.util.StringUtils.isEmpty(addressInfo.getName())){
            Snowflake snowflake = IdUtil.getSnowflake(workerId, (int) (Math.random() * 20 + 1));
            EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
            addressTreeInitial.setAreaName(addressInfo.getName());
            if (!org.springframework.util.StringUtils.isEmpty(addressInfo.getResidentialId())){
                addressTreeInitial.setAddressId(addressInfo.getResidentialId());
            }else{
                addressTreeInitial.setAddressId(snowflake.nextId());
            }
            addressTreeInitial.setAreaType(AreaEnum.detail.getType());
            if (parseNodeList.size() - 1 >= 0){
                addressTreeInitial.setParentId(parseNodeList.get(parseNodeList.size() - 1).getAddressId());
            }
            parseNodeList.add(addressTreeInitial);
        }
        return address;
    }

    /**
     * 解析路，街
     *
     * @param address
     * @param addressInfo
     * @param parseNodeList
     * @return
     */
    String parseRoad(String address, AddressInfo addressInfo, List<EduAddressTreeInitialVO> parseNodeList) {
        if(StringUtils.isEmpty(addressInfo.getRoad())){
            Matcher matcher = PATTERN_ROAD.matcher(address);
            String matcherText = "";
            if (matcher.find()) {
                // 获取匹配的部分
                matcherText = matcher.group();
                Matcher numberMather = PATTERN_ROAD_NUMBER.matcher(matcherText);
                if (numberMather.find()) {
                    String roadNumber = numberMather.group();
                    //有路编号就设置路编号
                    addressInfo.setRoadNumber(roadNumber);
                    address = address.replace(roadNumber, "");
                    matcherText = matcherText.replace(roadNumber, "");
                }else{
                    address = address.replace(matcherText, "");
                    //判断号中间是否有方向名称 如：东1666号
                    Matcher prefixMatcher = PATTERN_ROAD_PREFIX.matcher(address);
                    if (prefixMatcher.find()) {
                        //取出东1666号
                        String prefixText = prefixMatcher.group();
                        //取出路编号 166号
                        Matcher roadNumberMatcher = PATTERN_ROAD_NUMBER.matcher(prefixText);
                        if (roadNumberMatcher.find()){
                            String roadNumberText = roadNumberMatcher.group();
                            address = address.replace(prefixText, "");
                            //设置路编号
                            addressInfo.setRoadNumber(roadNumberText);
                        }
                    }
                }
            }
            //设置路信息
            addressInfo.setRoad(matcherText);
            if (!address.startsWith(matcherText)){
                address = setPrefixNode(address,matcherText,parseNodeList);
            }else{
                //如果是以matcherText开头，就直接去除
                address = address.replace(matcherText, "");
            }
        }
        //设置集合信息
        //设置 road
        if (!org.springframework.util.StringUtils.isEmpty(addressInfo.getRoad())){
            Snowflake snowflake = IdUtil.getSnowflake(workerId, (int) (Math.random() * 20 + 1));
            EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
            addressTreeInitial.setAreaName(addressInfo.getRoad());
            if (!org.springframework.util.StringUtils.isEmpty(addressInfo.getRoadId())){
                addressTreeInitial.setAddressId(addressInfo.getRoadId());
            }else{
                addressTreeInitial.setAddressId(snowflake.nextId());
            }
            addressTreeInitial.setAreaType(AreaEnum.road.getType());
            if (parseNodeList.size() - 1 >= 0){
                addressTreeInitial.setParentId(parseNodeList.get(parseNodeList.size() - 1).getAddressId());
            }
            parseNodeList.add(addressTreeInitial);
        }
        //设置roadNumber
        if (!org.springframework.util.StringUtils.isEmpty(addressInfo.getRoadNumber())){
            Snowflake snowflake = IdUtil.getSnowflake(workerId, (int) (Math.random() * 20 + 1));
            EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
            addressTreeInitial.setAreaName(addressInfo.getRoadNumber());
            addressTreeInitial.setAddressId(snowflake.nextId());
            addressTreeInitial.setAreaType(AreaEnum.roadNumber.getType());
            if (parseNodeList.size()-1 >= 0){
                addressTreeInitial.setParentId(parseNodeList.get(parseNodeList.size() - 1).getAddressId());
            }
            parseNodeList.add(addressTreeInitial);
        }
        return address;
    }

    String parseRoomNumber(String address, AddressInfo addressInfo, List<EduAddressTreeInitialVO> parseNodeList) {
        if(StringUtils.isEmpty(addressInfo.getRoomNumber())){
            Matcher matcher = PATTERN_ROOM_NUMBER.matcher(address);
            String matcherText = "";
            if (matcher.find()) {
                // 获取匹配的部分
                matcherText = matcher.group();
            }
            //设置房间号
            addressInfo.setRoomNumber(matcherText);
            //判断address 是否以matcherText开头
            if (!address.startsWith(matcherText)){
                address = setPrefixNode(address,matcherText,parseNodeList);
            }else{
                //如果是以matcherText开头，就直接去除
                address = address.replace(matcherText, "");
            }
        }
        //设置roomNumber 房间编号
        if (!org.springframework.util.StringUtils.isEmpty(addressInfo.getRoomNumber())){
            Snowflake snowflake = IdUtil.getSnowflake(workerId, (int) (Math.random() * 20 + 1));
            EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
            addressTreeInitial.setAreaName(addressInfo.getRoomNumber());
            addressTreeInitial.setAddressId(snowflake.nextId());
            addressTreeInitial.setAreaType(AreaEnum.roomNumber.getType());
            if (parseNodeList.size() -1 >= 0){
                addressTreeInitial.setParentId(parseNodeList.get(parseNodeList.size() -1 ).getAddressId());
            }
            parseNodeList.add(addressTreeInitial);
        }
        return address;
    }

    String parseUnitNumber(String address, AddressInfo addressInfo, List<EduAddressTreeInitialVO> parseNodeList) {
        if(StringUtils.isEmpty(addressInfo.getUnitNumber())){
            Matcher matcher = PATTERN_UNIT.matcher(address);
            String matcherText = "";
            if (matcher.find()) {
                // 获取匹配的部分
                matcherText = matcher.group();
            }
            //设置村单元编号
            addressInfo.setUnitNumber(matcherText);
            //判断address 是否以matcherText开头
            if (!address.startsWith(matcherText)){
                address = setPrefixNode(address,matcherText,parseNodeList);
            }else{
                //如果是以matcherText开头，就直接去除
                address = address.replace(matcherText, "");
            }
        }
        //设置unitNumber 单元编号
        if (!org.springframework.util.StringUtils.isEmpty(addressInfo.getUnitNumber())){
            Snowflake snowflake = IdUtil.getSnowflake(workerId, (int) (Math.random() * 20 + 1));
            EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
            addressTreeInitial.setAreaName(addressInfo.getUnitNumber());
            addressTreeInitial.setAddressId(snowflake.nextId());
            addressTreeInitial.setAreaType(AreaEnum.unitNumber.getType());
            if (parseNodeList.size() -1 >= 0){
                addressTreeInitial.setParentId(parseNodeList.get(parseNodeList.size() - 1).getAddressId());
            }
            parseNodeList.add(addressTreeInitial);
        }
        return address;
    }

    String parseHouseNumber(String address, AddressInfo addressInfo, List<EduAddressTreeInitialVO> parseNodeList) {
        if(StringUtils.isEmpty(addressInfo.getHouseNumber())){
            Matcher matcher = PATTERN_HOUSE.matcher(address);
            String matcherText = "";
            if (matcher.find()) {
                // 获取匹配的部分
                matcherText = matcher.group();
            }
            //设置楼房编号 几幢
            addressInfo.setHouseNumber(matcherText);
            //判断address 是否以matcherText开头
            if (!address.startsWith(matcherText)){
                address = setPrefixNode(address,matcherText,parseNodeList);
            }else{
                //如果是以matcherText开头，就直接去除
                address = address.replace(matcherText, "");
            }
        }
        //设置houseNumber
        if (!org.springframework.util.StringUtils.isEmpty(addressInfo.getHouseNumber())){
            Snowflake snowflake = IdUtil.getSnowflake(workerId, (int) (Math.random() * 20 + 1));
            EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
            addressTreeInitial.setAreaName(addressInfo.getHouseNumber());
            addressTreeInitial.setAddressId(snowflake.nextId());
            addressTreeInitial.setAreaType(AreaEnum.houseNumber.getType());
            if (parseNodeList.size() - 1 >= 0){
                addressTreeInitial.setParentId(parseNodeList.get(parseNodeList.size() - 1).getAddressId());
            }
            parseNodeList.add(addressTreeInitial);
        }
        return address;
    }

    /**
     * 解析村，社区，花园，小区信息
     *
     * @param address
     * @param addressInfo
     * @param parseNodeList
     * @return
     */
    String parseVillage(String address, AddressInfo addressInfo, List<EduAddressTreeInitialVO> parseNodeList) {
        if(StringUtils.isEmpty(addressInfo.getVillage())){
            String matcherText = "";
            Matcher matcher = PATTERN_VILLAGE.matcher(address);
            if (matcher.find()) {
                // 获取匹配的部分
                matcherText = matcher.group();
                //判断是否有路
                Matcher roadMatcher = PATTERN_ROAD.matcher(matcherText);
                if (roadMatcher.find()){
                    String roadText = roadMatcher.group();
                    //中街
                    if (!roadText.equals(matcherText)){
                        if (matcherText.replace(roadText,"").length()>=2){
                            matcherText =  matcherText.replace(roadText,"");
                        }
                    }
                }
                //判断是否有楼房
                Matcher houseMatcher = PATTERN_HOUSE.matcher(matcherText);
                if (houseMatcher.find()){
                    String houseText = houseMatcher.group();
                    if (!houseText.equals(matcherText)){
                        matcherText =  matcherText.replace(houseText,"");
                    }
                }
                //判断是否有门牌号
                Matcher unitMatcher = PATTERN_UNIT.matcher(matcherText);
                if (unitMatcher.find()){
                    String unitText = unitMatcher.group();
                    if (!unitText.equals(matcherText)){
                        matcherText =  matcherText.replace(unitText,"");
                    }
                }
                //判断房间
                Matcher roomMatcher = PATTERN_ROOM_NUMBER.matcher(matcherText);
                if (roomMatcher.find()){
                    String roomText = roomMatcher.group();
                    if (!roomText.equals(matcherText)){
                        matcherText =  matcherText.replace(roomText,"");
                    }
                }
                //设置村/社区信息
                addressInfo.setVillage(matcherText);
                //判断address 是否以matcherText开头
                if (!address.startsWith(matcherText)){
                    address = setPrefixNode(address,matcherText,parseNodeList);
                }else{
                    //如果是以matcherText开头，就直接去除
                    address = address.replace(matcherText, "");
                }
            }
        }
        //设置集合信息
        if (!org.springframework.util.StringUtils.isEmpty(addressInfo.getVillage())){
            Snowflake snowflake = IdUtil.getSnowflake(workerId, (int) (Math.random() * 20 + 1));
            EduAddressTreeInitialVO addressTreeInitial = new EduAddressTreeInitialVO();
            addressTreeInitial.setAreaName(addressInfo.getVillage());
            if (addressInfo.getVillageId()!=null){
                addressTreeInitial.setAddressId(addressInfo.getVillageId());
            }else{
                addressTreeInitial.setAddressId(snowflake.nextId());
            }
            if (!org.springframework.util.StringUtils.isEmpty(addressInfo.getVillageCode())){
                addressTreeInitial.setAreaCode(addressInfo.getVillageCode());
            }
            addressTreeInitial.setAreaType(AreaEnum.village.getType());
            if (parseNodeList.size() -1 >= 0){
                addressTreeInitial.setParentId(parseNodeList.get(parseNodeList.size() -1).getAddressId());
            }
            parseNodeList.add(addressTreeInitial);
        }
        return address;
    }

    /**
     * 如果address不以matcherText开头，取出前缀文本并且设置到list中
     * @param address 要解析的地址
     * @param matcherText 匹配到的节点
     * @param parseNodeList 解析节点列表
     * @return
     */
    private String setPrefixNode(String address, String matcherText, List<EduAddressTreeInitialVO> parseNodeList) {
        Snowflake snowflake = IdUtil.getSnowflake(workerId, (int) (Math.random() * 20 + 1));
        // 如果不为开头，裁剪address中的部分文本并取出
        int index = address.indexOf(matcherText);
        //保证开头有其他字段
        if (index > 0) {
            String otherText = address.substring(0, index).trim();
            //设置其他文本到list中
            EduAddressTreeInitialVO otherNode = new EduAddressTreeInitialVO();
            otherNode.setAddressId(snowflake.nextId());
            otherNode.setAreaType(AreaEnum.other.getType());
            otherNode.setAreaName(otherText);
            if (parseNodeList.size() -1 >= 0){
                otherNode.setParentId(parseNodeList.get(parseNodeList.size() -1).getAddressId());
            }
            parseNodeList.add(otherNode);
            address = address.substring(index + matcherText.length()).trim();
        }
        return address;
    }

    private String parseTown(String address,AddressInfo addressInfo) {
        Matcher matcher = PATTERN_TWON.matcher(address);
        String matcherText = "";
        if (matcher.matches()) {
            // 返回匹配的部分
            matcherText = matcher.group();
        }else{
            //分词
            List<String> addressList = new ArrayList<>();
            try {
                addressList = IKAnalyzerUtil.wordSegmentationToList(address);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            if(!CollectionUtils.isEmpty(addressList)){
                for (String addressText : addressList) {
                    Matcher twonMatcher = PATTERN_TWON.matcher(addressText);
                    if (twonMatcher.find()) {
                        matcherText=matcherText+addressText;
                        break;
                    }
                }
            }
        }
        //设置乡镇信息
        addressInfo.setTown(matcherText);
        return  address.replace(matcherText, "");
    }

    private List<Address> matchText(List<String> textList,Long addressId){
        List<Address> addressList=new ArrayList<>();
        String matcherText="";
        int matcherCount=0;
        boolean matchFlag=false;
        String areaType=AreaEnum.other.getType();
        //村社区
        for (String str : textList) {
            Matcher matcher = PATTERN_VILLAGE.matcher(matcherText);
            if (matcher.find()) {
                matcherCount=matcherCount+1;
                areaType=AreaEnum.village.getType();
                matcherText=matcherText+str;
                matchFlag=true;
            }else{
                if (matchFlag&&matcherCount>0){
                    Address address=new Address();
                    address.setAreaName(matcherText);
                    address.setAreaType(areaType);
                    matchFlag=false;
                    matcherCount=0;
                    areaType=AreaEnum.other.getType();
                    matcherText=str;
                }else{
                    matcherText=matcherText+str;
                }
            }

        }
        return new ArrayList<>();
    }
    private String replace( List<AlternativeData> list,TextHolder textHolder){
        if (!CollUtil.isEmpty(list)){
            for(AlternativeData alternativeData:list){
                textHolder.removeText(alternativeData.getMatchValue());
            }

        }
        return textHolder.getText();
    }
    public Address getAddressByMap(Long id) {
        if (!initAreaMap) {
            initAreaMap();
        }
        return areaMap.get(id);
    }


    private synchronized void initAreaMap() {
        if (initAreaMap) {
            return;
        }
        initAreaMap(addressDataLoader.loadData());
        initAreaMap = true;
    }

    private void initAreaMap(List<Address> addresses) {
        if (CollUtil.isEmpty(addresses)) {
            return;
        }
        for (Address loadDatum : addresses) {
            areaMap.put(loadDatum.getAddressId(), loadDatum);
            initAreaMap(loadDatum.getChildren());
        }
    }



    /**
     * 解析符合条件的结果
     *
     * @param text 未解析文本
     * @param dataList 匹配到的列表
     * @param addressInfo 地址解析返回结果
     * @param areaCodeList 当前统筹区化所属编码
     * @param areaNodeOriginals 当前统筹区化对应参数表节点
     * @return
     */
    public List<AlternativeData> bestMatch(String text, int level, List<AlternativeData> dataList,AddressInfo addressInfo,List<String> areaCodeList, List<EduAddressTreeOriginal> areaNodeOriginals) {
        List<Address> addressList =new ArrayList<>();
        if (CollUtil.isEmpty(dataList)) {
            addressList=AddressDataUtil.getAssignLevel(addressAll, level,addressInfo).stream().distinct().collect(Collectors.toList());
            //如果为街道的时候，过滤出真正的街道
            // if(level == 3){
            //     addressList = addressList.stream()
            //             .filter(address -> "town".equals(address.getAreaType()))
            //             .collect(Collectors.toList());
            // }
        }else{
            addressList =dataList.get(0).getData().getChildren();
            //如果为街道的时候，过滤出真正的街道
            // if(level == 3){
            //     addressList = addressList.stream()
            //             .filter(address -> "town".equals(address.getAreaType()))
            //             .collect(Collectors.toList());
            // }
        }
        //匹配街道的，优先匹配配置统筹区化所属区下的街道信息
        if (level == 3 || level ==2){
            if (level == 2){
                List<AlternativeData> match = match(text, level, addressList, null, addressInfo);
                //如果match存在，比对统筹区化
                addressInfo.setIsOtherCity(false);
                if(!CollectionUtils.isEmpty(match)){
                    AlternativeData alternativeData = match.get(0);
                    Address address = alternativeData.getData();
                    //如果有值，并且行政区划在areaCodeList，表示是统筹区化下的地址
                    if (!areaCodeList.contains(address.getAreaCode())){
                        //表示当前地址不是统筹区化地址，
                        addressInfo.setIsOtherCity(true);
                    }
                }
                return match;
            }
//            if (!CollUtil.isEmpty(areaCodeList)){
//                List<Address> redisAddressList=null;
//                if(redisHelper.hasKey(EduCache.EDU_ADDRESS_TREE_MATCH_AREA)){
//                    redisAddressList=JSON.parseArray(redisHelper.get(EduCache.EDU_ADDRESS_TREE_MATCH_AREA).toString(),Address.class) ;
//                }
//                if(!CollectionUtils.isEmpty(redisAddressList)){
//                    addressList=redisAddressList;
//                }else{
//                    List<Long> addressIds = areaNodeOriginals.stream().map(EduAddressTreeOriginal::getAddressId).collect(Collectors.toList());
//                    //匹配区县时
//                    addressList = addressList.stream().filter(address -> addressIds.contains(address.getParentId())).collect(Collectors.toList());
//                    if(!CollectionUtils.isEmpty(addressList)){
//                        redisHelper.set(EduCache.EDU_ADDRESS_TREE_MATCH_AREA, JSON.toJSONString(addressList),7200);
//                    }
//                }
//            }
            List<Long> addressIds = areaNodeOriginals.stream().map(EduAddressTreeOriginal::getAddressId).collect(Collectors.toList());
            //匹配区县时
            addressList = addressList.stream().filter(address -> addressIds.contains(address.getParentId())).collect(Collectors.toList());
            //匹配街道时
            if (level == 3){
                List<AlternativeData> match = match(text, level, addressList, null, addressInfo);
                if(!CollectionUtils.isEmpty(match)){
                    //将街道id取出，用于判断匹配的街道是否为行政区划下的街道信息
                    List<Long> addressId = addressList.stream().map(Address::getAddressId).collect(Collectors.toList());
                    AlternativeData alternativeData = match.get(0);
                    //如果有值，并且行政区划在areaCodeList，表示是统筹区化下的地址
                    if (!addressId.contains(alternativeData.getAddressId())){
                        //表示当前地址不是统筹区化地址，
                        addressInfo.setIsOtherCity(true);
                    }else{
                        addressInfo.setIsOtherCity(false);
                    }
                }
                return match;
            }
        }
        return match(text, level, addressList, null,addressInfo);

//        Map<Long, List<Address>> groupList = addressList.stream()
//                .collect(Collectors.groupingBy(Address::getParentId));
//        List<AlternativeData> alternativeList = new ArrayList<>();
//        for (AlternativeData alternativeData : dataList) {
//            groupList.forEach((parentId, addresses) -> {
//                if (!alternativeData.getAddressId().equals(parentId)) {
//                    return;
//                }
//                alternativeList.addAll(match(text, level, addresses, alternativeData,addressInfo));
//            });
//        }
//        return alternativeList;
    }


    /**
     * 匹配节点的方法
     * @param text 要匹配的地址文本
     * @param level 级别
     * @param addressList 地址集合列表
     * @param parentData 父节点
     * @param addressInfo 匹配结果对象
     * @return
     */
    public List<AlternativeData> match(String text, int level, List<Address> addressList,
                                       AlternativeData parentData,AddressInfo addressInfo) {

        if (CollUtil.isEmpty(addressList)) {
            return Collections.emptyList();
        }
//        text = ReUtil.replaceFirst(keyCharPattern, text, "");
        // 清楚特殊字符后
        String clearSpecialLat = ReUtil.replaceAll(text, RegexConstant.SPECIAL, "");
        Map<Long, AlternativeData> matchProvince = new HashMap<>();
        List<AlternativeData> result = new ArrayList<>();

        String keyword="";
        for (Address data : addressList) {
            // 如果名称与地址一致，则为最有匹配
            if (clearSpecialLat.startsWith(data.getAreaName())) {
                keyword = data.getAreaName(); // 默认关键词为地址名
                // 如果有别名，则尝试匹配
                if (StringUtils.isNotBlank(data.getSearchTerm())) {
                    List<String> nameList = Arrays.stream(data.getSearchTerm().split("#"))
                            .sorted(Comparator.comparing(String::length).reversed()) // 按字符串长度降序排序
                            .filter(name -> name.length() >= 2 && clearSpecialLat.startsWith(name)) // 判断是否以别名开头
                            .filter(name -> checkSearchName(data, clearSpecialLat, name))// 判断别名是否符合要求
                            .collect(Collectors.toList());
                    if (!nameList.isEmpty()) {
                        if (nameList.get(0).length() > keyword.length()){
                            //如果别名的长度大于关键词的长度，则替换关键字
                            keyword = nameList.get(0); // 获取第一个符合条件的别名
                        }
                    }
                }

                AlternativeData alternativeData = new AlternativeData(data, parentData, level, keyword);
                matchProvince.put(data.getAddressId(), alternativeData);
                result.add(alternativeData);
            }else {
                //地址名找不到去找别名
                if (StringUtils.isNotBlank(data.getSearchTerm())){
                    List<String> nameList = Arrays.stream(data.getSearchTerm().split("#"))
                            .sorted(Comparator.comparing(String::length).reversed()) // 按字符串长度降序排序
                            .collect(Collectors.toList());
                    boolean matchFlag=false;
                    for (String name:nameList){
                        if (name.length()>=2&&clearSpecialLat.startsWith(name)) {
                            //校验匹配别名是否正确
                            if (!checkSearchName(data, clearSpecialLat, name)){
                                matchFlag=false;
                                continue;
                            }
                            keyword=name;
                            matchFlag=true;
                            break;
                        }
                    }
                    if (matchFlag){
                        AlternativeData alternativeData=new AlternativeData(data, parentData, level, keyword);
                        matchProvince.put(data.getAddressId(), alternativeData);
                        result.add(alternativeData);
                    }
                }
            }
        }
//        if (!matchProvince.isEmpty()) {
//            // 重庆有重庆城区和县区，所以这里size<=2
//            if (addressList.size() <= 2 ) {
//                // 取前两个字
//                List<AlternativeData> data = new ArrayList<>();
//                for (Address address : addressList) {
//                    data.add(new AlternativeData(address, parentData, level, ""));
//                }
//                return data;
//            }
//        }
        //如果有多个，建立长度和名字的map
        List<String> longestAreaNames = result.stream()
                .map(alternativeData -> alternativeData.getData().getAreaName())
                .filter(name -> name.length() == result.stream()
                        .mapToInt(alternativeData -> alternativeData.getData().getAreaName().length())
                        .max().orElse(0))
                .collect(Collectors.toList());
        if(longestAreaNames.size() ==1){
            String longestName = longestAreaNames.get(0);
            AlternativeData longestAlternativeData = result.stream()
                    .filter(alternativeData -> alternativeData.getData().getAreaName().equals(longestName))
                    .findFirst()
                    .orElse(null);
            result.clear();
            result.add(longestAlternativeData);
        }


        if (result.size() == 1) {
            setAddressInfo(result.get(0).getData(),addressInfo);
            return result;
        }else{
            return new ArrayList<>(matchProvince.values());
        }
    }

    /**
     * 校验匹配到别名是否符合要求
     * @param data 参数地址节点
     * @param clearSpecialLat  解析的剩余地址
     * @param name  匹配到的字段前缀
     * @return
     */
    private Boolean checkSearchName(Address data, String clearSpecialLat, String name) {
        String remainingPart = clearSpecialLat.substring(name.length());
        // 如果匹配的是市
        if (data.getAreaType().equals(AreaEnum.city.getType()) ||
                data.getAreaType().equals(AreaEnum.district.getType())) {
            // 获取 name 后的字符
            return !startWithOfWords(remainingPart);
        }
        return true;
    }

    /**
     * 判断是否以特殊字符开头
     * @param input
     * @return
     */
    private boolean startWithOfWords(String input) {
        //剩下的字段 以以下字符开头则不通过
        return input.startsWith("街") ||
                input.startsWith("街道") ||
                input.startsWith("门") ||
                input.startsWith("路")||
                input.startsWith("小区");
    }

//    private void setAddressInfo(Address data,AddressInfo addressInfo){
//        if (AreaEnum.province.getType().equalsIgnoreCase(data.getAreaType())){
//            addressInfo.setProvinceId(data.getAddressId());
//            addressInfo.setProvince(data.getAreaName());
//            addressInfo.setProvinceCode(data.getAreaCode());
//        }else if(AreaEnum.city.getType().equalsIgnoreCase(data.getAreaType())){
//            if (addressInfo.getProvinceId()==null){
//                Address province=getAddressByMap(data.getParentId());
//                if (province!=null){
//                    addressInfo.setProvinceId(province.getAddressId());
//                    addressInfo.setProvince(province.getAreaName());
//                    addressInfo.setProvinceCode(province.getAreaCode());
//                }
//            }
//            addressInfo.setCityId(data.getAddressId());
//            addressInfo.setCity(data.getAreaName());
//            addressInfo.setCityCode(data.getAreaCode());
//        }else if(AreaEnum.district.getType().equalsIgnoreCase(data.getAreaType())){
//            if (addressInfo.getCityId()==null){
//                Address city=getAddressByMap(data.getParentId());
//                if (city!=null){
//                    addressInfo.setCityId(city.getAddressId());
//                    addressInfo.setCity(city.getAreaName());
//                    addressInfo.setCityCode(city.getAreaCode());
//                    if (addressInfo.getProvinceId()==null){
//                        Address province=getAddressByMap(city.getParentId());
//                        if (province!=null){
//                            addressInfo.setProvinceId(province.getAddressId());
//                            addressInfo.setProvince(province.getAreaName());
//                            addressInfo.setProvinceCode(province.getAreaCode());
//                        }
//                    }
//                }
//            }
//            addressInfo.setDistrictId(data.getAddressId());
//            addressInfo.setDistrict(data.getAreaName());
//            addressInfo.setDistrictCode(data.getAreaCode());
//        }else if(AreaEnum.town.getType().equalsIgnoreCase(data.getAreaType())){
//            if (addressInfo.getDistrictId()==null){
//                Address district=getAddressByMap(data.getParentId());
//                if (district!=null){
//                    addressInfo.setDistrictId(district.getAddressId());
//                    addressInfo.setDistrict(district.getAreaName());
//                    addressInfo.setDistrictCode(district.getAreaCode());
//                    if (addressInfo.getCityId()==null){
//                        Address city=getAddressByMap(district.getParentId());
//                        if (city!=null){
//                            addressInfo.setCityId(city.getAddressId());
//                            addressInfo.setCity(city.getAreaName());
//                            addressInfo.setCityCode(city.getAreaCode());
//                            if (addressInfo.getProvinceId()==null){
//                                Address province=getAddressByMap(city.getParentId());
//                                if (province!=null){
//                                    addressInfo.setProvinceId(province.getAddressId());
//                                    addressInfo.setProvince(province.getAreaName());
//                                    addressInfo.setProvinceCode(province.getAreaCode());
//                                }
//                            }
//                        }
//                    }
//                }
//            }
//            addressInfo.setTownId(data.getAddressId());
//            addressInfo.setTown(data.getAreaName());
//            addressInfo.setTownCode(data.getAreaCode());
//        }else if(AreaEnum.village.getType().equalsIgnoreCase(data.getAreaType())){
//            if (addressInfo.getTownId()==null){
//                Address town=getAddressByMap(data.getParentId());
//                if (town!=null){
//                    addressInfo.setTownId(town.getAddressId());
//                    addressInfo.setTown(town.getAreaName());
//                    addressInfo.setTownCode(town.getAreaCode());
//                    if (addressInfo.getDistrictId()==null){
//                        Address district=getAddressByMap(town.getParentId());
//                        if (district!=null){
//                            addressInfo.setDistrictId(district.getAddressId());
//                            addressInfo.setDistrict(district.getAreaName());
//                            addressInfo.setDistrictCode(district.getAreaCode());
//                            if (addressInfo.getCityId()==null){
//                                Address city=getAddressByMap(district.getParentId());
//                                if (city!=null){
//                                    addressInfo.setCityId(city.getAddressId());
//                                    addressInfo.setCity(city.getAreaName());
//                                    addressInfo.setCityCode(city.getAreaCode());
//                                    if (addressInfo.getProvinceId()==null){
//                                        Address province=getAddressByMap(city.getParentId());
//                                        if (province!=null){
//                                            addressInfo.setProvinceId(province.getAddressId());
//                                            addressInfo.setProvince(province.getAreaName());
//                                            addressInfo.setProvinceCode(province.getAreaCode());
//                                        }
//                                    }
//                                }
//                            }
//                        }
//                    }
//                }
//            }
//            addressInfo.setVillageId(data.getAddressId());
//            addressInfo.setVillage(data.getAreaName());
//            addressInfo.setVillageCode(data.getAreaCode());
////        }else if(AreaEnum.road.getType().equalsIgnoreCase(data.getAreaType())){
////            addressInfo.setRoadId(data.getAddressId());
////            addressInfo.setRoad(data.getAreaName());
//        }else if(AreaEnum.detail.getType().equals(data.getAreaType())){
//            if (addressInfo.getVillageId()==null){
//                Address village=getAddressByMap(data.getParentId());
//                if (village!=null){
//                    addressInfo.setVillageId(village.getAddressId());
//                    addressInfo.setVillage(village.getAreaName());
//                    addressInfo.setVillageCode(village.getAreaCode());
//                    if (addressInfo.getTownId()==null){
//                        Address town=getAddressByMap(village.getParentId());
//                        if (town!=null){
//                            addressInfo.setTownId(town.getAddressId());
//                            addressInfo.setTown(town.getAreaName());
//                            addressInfo.setTownCode(town.getAreaCode());
//                        }
//                    }
//                }
//            }
//            addressInfo.setName(data.getAreaName());
//            addressInfo.setResidentialId(data.getAddressId());
//        }
//    }

    /**
     * 表示匹配到了参数表数据，就设置节点消息
     * @param data
     * @param addressInfo
     */
    public void setAddressInfo(Address data,AddressInfo addressInfo) {
        setAddressInfoRecursive(addressInfo, data);
    }

    /**
     * 递归设置节点消息
     * @param addressInfo
     * @param data
     */
    public void setAddressInfoRecursive(AddressInfo addressInfo, Address data) {
        if (AreaEnum.province.getType().equalsIgnoreCase(data.getAreaType())) {
            setAddressInfoFromAddressData(addressInfo, data);
        } else {
            Address parent = getAddressByMap(data.getParentId());
            if (parent != null) {
                setAddressInfoRecursive(addressInfo, parent);
            }
            setAddressInfoFromAddressData(addressInfo, data);
        }
    }

    /**
     * 设置匹配到的节点信息
     * @param addressInfo
     * @param data
     */
    private void setAddressInfoFromAddressData(AddressInfo addressInfo, Address data) {
        switch (AreaEnum.valueOf(data.getAreaType())) {
            case province:
                addressInfo.setProvinceId(data.getAddressId());
                addressInfo.setProvince(data.getAreaName());
                addressInfo.setProvinceCode(data.getAreaCode());
                break;
            case city:
                addressInfo.setCityId(data.getAddressId());
                addressInfo.setCity(data.getAreaName());
                addressInfo.setCityCode(data.getAreaCode());
                break;
            case district:
                addressInfo.setDistrictId(data.getAddressId());
                addressInfo.setDistrict(data.getAreaName());
                addressInfo.setDistrictCode(data.getAreaCode());
                break;
            case town:
                addressInfo.setTownId(data.getAddressId());
                addressInfo.setTown(data.getAreaName());
                addressInfo.setTownCode(data.getAreaCode());
                break;
//            case village:
//                addressInfo.setVillageId(data.getAddressId());
//                addressInfo.setVillage(data.getAreaName());
//                addressInfo.setVillageCode(data.getAreaCode());
//                break;
//            case road:
//                addressInfo.setRoadId(data.getAddressId());
//                addressInfo.setRoad(data.getAreaName());
//                break;
//            case detail:
//                addressInfo.setResidentialId(data.getAddressId());
//                addressInfo.setName(data.getAreaName());
//                break;
        }
    }
    private void setAddressInfoProvince(Address data,AddressInfo addressInfo){
        if (AreaEnum.province.getType().equalsIgnoreCase(data.getAreaType())){
            addressInfo.setProvinceId(data.getAddressId());
            addressInfo.setProvince(data.getAreaName());
            addressInfo.setProvinceCode(data.getAreaCode());
        }else if(AreaEnum.city.getType().equalsIgnoreCase(data.getAreaType())){
            if (addressInfo.getProvinceId()==null){
                Address province=getAddressByMap(data.getParentId());
                if (province!=null){
                    addressInfo.setProvinceId(province.getAddressId());
                    addressInfo.setProvince(province.getAreaName());
                    addressInfo.setProvinceCode(province.getAreaCode());
                }
            }
        }else if(AreaEnum.district.getType().equalsIgnoreCase(data.getAreaType())){
            if (addressInfo.getCityId()==null){
                Address city=getAddressByMap(data.getParentId());
                if (city!=null){

                    if (addressInfo.getProvinceId()==null){
                        Address province=getAddressByMap(city.getParentId());
                        if (province!=null){
                            addressInfo.setProvinceId(province.getAddressId());
                            addressInfo.setProvince(province.getAreaName());
                            addressInfo.setProvinceCode(province.getAreaCode());
                        }
                    }
                }
            }
        }else if(AreaEnum.town.getType().equalsIgnoreCase(data.getAreaType())){
            if (addressInfo.getDistrictId()==null){
                Address district=getAddressByMap(data.getParentId());
                if (district!=null){
                    if (addressInfo.getCityId()==null){
                        Address city=getAddressByMap(district.getParentId());
                        if (city!=null){
                            if (addressInfo.getProvinceId()==null){
                                Address province=getAddressByMap(city.getParentId());
                                if (province!=null){
                                    addressInfo.setProvinceId(province.getAddressId());
                                    addressInfo.setProvince(province.getAreaName());
                                    addressInfo.setProvinceCode(province.getAreaCode());
                                }
                            }
                        }
                    }
                }
            }

        }
    }

}
